package org.redr.canvas;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sound.sampled.Line;

import com.trolltech.qt.core.QPointF;
import com.trolltech.qt.core.QRectF;
import com.trolltech.qt.core.QSizeF;
import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QBrush;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QGraphicsItemInterface;
import com.trolltech.qt.gui.QGraphicsPixmapItem;
import com.trolltech.qt.gui.QGraphicsRectItem;
import com.trolltech.qt.gui.QGraphicsScene;
import com.trolltech.qt.gui.QGraphicsView;
import com.trolltech.qt.gui.QIcon;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QPixmap;
import com.trolltech.qt.gui.QStyleOptionGraphicsItem;
import com.trolltech.qt.gui.QWidget;

public class RRWIcon extends QGraphicsRectItem{
	
	private WidgetRegistry		info;
	private String				tabname;
	private String				widgetID;
	private boolean			isProcessing 		= 	false;
	private boolean			needsProcessing		=	false;
	private boolean			progressBarShown	=	false;
	private int				progressBarValue	=	-1;
	private String				caption;
	private boolean			selected	=	false;
	private HashMap<String, String>		widgetState	=	new HashMap<String, String>();
	private ArrayList<Line>		inLines	=	new ArrayList<Line>();
	private ArrayList<Line>		outLines	=	new ArrayList<Line>();
	private QPixmap 				icon;
	private static QPixmap		cloneIcon	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "clone.png").getAbsolutePath());
	private static QPixmap		lockedIcon	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "locked.png").getAbsolutePath());
	private static QPixmap		imageLeftEdge	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "leftEdge.png").getAbsolutePath());
	private static QPixmap		imageRightEdge	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "rightEdge.png").getAbsolutePath());
	private static QPixmap		imageLeftEdgeG	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "leftEdgeG.png").getAbsolutePath());
	private static QPixmap		imageRightEdgeG	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "rightEdgeG.png").getAbsolutePath());
	private static QPixmap		imageLeftEdgeR	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "leftEdgeR.png").getAbsolutePath());
	private static QPixmap		imageRightEdgeR	=	new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "rightEdgeR.png").getAbsolutePath());
	private static QSizeF		edgeSize		=	new QSizeF(imageLeftEdge.size());
	private static QGraphicsPixmapItem	infoIcon = 	new QGraphicsPixmapItem(new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "info.png").getAbsolutePath()));
	private static QGraphicsPixmapItem	warningIcon = new QGraphicsPixmapItem(new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "warning.png").getAbsolutePath()));
	private static QGraphicsPixmapItem	errorIcon = new QGraphicsPixmapItem(new QPixmap(OSPath.join(RedRApplication.parentDir, "coreIcons", "error.png").getAbsolutePath()));
	private QPointF				oldPos;
	private QSizeF				widgetSize;
	private QGraphicsScene		canvas;
	private boolean				potentialConnection = false;
	private QGraphicsView		view;
	private QPixmap 			shownLeftEdge = imageLeftEdge;
	private QPixmap				shownRightEdge = imageRightEdge;
	
	public RRWIcon(QGraphicsScene canvas, QGraphicsView view, WidgetRegistry info, String widgetID){
		super(null, canvas);
		this.canvas = canvas;
		this.view = view;
		this.info = info;
		this.widgetID = widgetID;
		System.out.println("Adding icon with icon pixmap: " + info.icon);
		this.icon = new QPixmap(info.icon);
		
		infoIcon.hide();
		warningIcon.hide();
		errorIcon.hide();
		resetWidgetSize();
		setOldPos(this.pos());
		
		canvas.addItem(this);
		canvas.update();
	}
	
	public RRW instance(){
		return RedRObjects.getWidgetInstanceByID(widgetID);
	}
	
	public void resetWidgetSize(){
		int size	=	
				40;
		//		Integer.parseInt((String) RedRApplication.coreSettings().getSetting("iconSize"));
		setRect(0,0,size,size);
		widgetSize	=	new QSizeF(size, size);
	}
	
	public WidgetRegistry getWidgetInfo(){
		return info;
	}
	
	public void remove(){
		this.hide();
		errorIcon.hide();
		warningIcon.hide();
		infoIcon.hide();
		this.canvas.removeItem(this);
		
	}
	
	public void savePosition(){
		setOldPos(pos());
	}
	
	public void restorePosition(){
		setPos(getOldPos());
	}
	
	public void updateText(String text){
		caption	=	text;
		updateTooltip();
	}
	
	public void updateTooltip() {
		// TODO Auto-generated method stub
		
	}

	public void updateWidgetState(){
		// TODO fix
		
	}
	
	public void updateWidgetStateIcon(QIcon icon, int x, int y, HashMap<String, String> state){
		
	}
	
	public boolean isIconSelected(){
		return selected;
	}
	
	public void setIconSelected(boolean sel){
		selected =	sel;
	}
	
	public void setPossibleConnection(boolean canConnect){
		potentialConnection	=	canConnect;
	}
	
	public void setCoords(double x, double y){
		setPos(x, y);
		updateWidgetState();
		view.ensureVisible(this);
		view.scene().update();
	}
	
	@Override
	public QRectF boundingRect(){
		QPixmap pixmap	=	new QPixmap(200,40);
		QPainter	painter	=	new QPainter();
		painter.begin(pixmap);
		double width	=	0 > (painter.boundingRect(new QRectF(0,0,200,40), caption).width() - 60) ? 0 : ((painter.boundingRect(new QRectF(0,0,200,40), caption).width() - 60)/2);
		painter.end();
		
		QRectF rect = new QRectF(new QPointF(0,0), widgetSize);
		rect.adjust((-10-width), -4, (10+width), 25);
		return rect;
	}

	public String caption() {
		// TODO Auto-generated method stub
		return caption;
	}

	public QPointF getRightEdgePoint() {
		// TODO Auto-generated method stub
		return new QPointF(x() + widgetSize.width() + edgeSize.width(), y() + widgetSize.height()/2);
	}

	public QPointF getLeftEdgePoint() {
		// TODO Auto-generated method stub
		return new QPointF(x() - edgeSize.width(), y() + widgetSize.height()/2);
	}
	
	
	@Override
	public void paint(QPainter painter, QStyleOptionGraphicsItem option, QWidget widget){
		// System.out.println("Painting the icon using the override paint function");
		QColor color = QColor.blue;
		// System.out.println("Is item selected:" + isSelected());
		if (isProcessing) color = new QColor(RedRApplication.coreSettings().getSetting("activeColor"));
		else if (selected) {
			// System.out.println("Item is selected");
			List<QGraphicsItemInterface> collisions = canvas.collidingItems(this);
			boolean collidesWithIcon = false;
			for (QGraphicsItemInterface i : collisions){
				if (i.getClass().equals(this.getClass())) collidesWithIcon = true;
			} 
			
			if (collidesWithIcon)	color = QColor.red;
			else color = new QColor(RedRApplication.coreSettings().getSetting("widgetSelectedColor"));
			
		} else if (potentialConnection) color = QColor.blue;
		if (isProcessing || selected || potentialConnection){
			painter.setPen(color);
			painter.drawRect(-3,-3, (int) widgetSize.width()+6, (int) widgetSize.height()+6);
		}
		
		painter.drawPixmap(0, 0, 
				//icon.pixmap((int) widgetSize.width(), (int) widgetSize.height())
				icon);
		if (instance().inputs().size() > 0){
			painter.drawPixmap(
					(int) -edgeSize.width(), 
					(int) (widgetSize.height()
							-edgeSize.height())/2,
							shownLeftEdge);
		}
		if (instance().outputs().size() > 0){
			painter.drawPixmap(
					(int) widgetSize.width(),
					(int) (widgetSize.height()
							-edgeSize.height())/2,
							shownRightEdge);
		}
		
		painter.setPen(QColor.black);
		double midX = widgetSize.width()/2.0;
		double midY = widgetSize.height() + 5.0;
		painter.drawText((int) midX - 100, (int) midY, 200, 20, new Qt.Alignment(Qt.AlignmentFlag.AlignTop, Qt.AlignmentFlag.AlignHCenter).value(), instance().caption());
		
		int yPos = -22;
		if (progressBarValue >= 0 && progressBarValue <= 100){
			QRectF rect = new QRectF(0, yPos, widgetSize.width(), 16);
			painter.setPen(new QColor(0,0,0));
			painter.setBrush(new QBrush(new QColor(255,255,255)));
			painter.drawRect(rect);
			
			painter.setBrush(new QBrush(new QColor(0,128,255)));
			painter.drawRect(new QRectF(0,yPos,widgetSize.width()*progressBarValue/100.0, 16));
			painter.drawText(rect, String.format("%d %%", progressBarValue));
			
		}
		
		// paint the fancy lock of the signal is locked
		if (instance().signalLocked()){
			painter.drawPixmap(20, -20, lockedIcon);
		}
	}

	public boolean insideRightChannel(QPointF mouseDownPosition) {
		if (instance().inputs().size() < 1) return false;
		QRectF boxRect = new QRectF(x()-edgeSize.width(), y() + (widgetSize.height() - edgeSize.height())/2,edgeSize.width(),edgeSize.height());
		boxRect.adjust(-10, -10, 5, 10);
		if (boxRect.contains(mouseDownPosition)) return true;
		return false;
	}

	public boolean insideLeftChannel(QPointF mouseDownPosition) {
		if (instance().outputs().size() < 1) return false;
		QRectF boxRect = new QRectF(x()+widgetSize.width(), y() + (widgetSize.height() - edgeSize.height())/2,edgeSize.width(),edgeSize.height());
		boxRect.adjust(-5, -10, 10, 10);
		if (boxRect.contains(mouseDownPosition)) return true;
		return false;
	}

	public double getDistToRightEdgePoint(QPointF mouseDownPosition) {
		QPointF p = getRightEdgePoint();
		double xdiff = mouseDownPosition.x() - p.x();
		double ydiff = mouseDownPosition.y() - p.y();
		double dist = Math.sqrt(Math.pow(xdiff, 2) + Math.pow(ydiff, 2));
		return dist;
	}
	
	public double getDistToLeftEdgePoint(QPointF mouseDownPosition) {
		QPointF p = getLeftEdgePoint();
		double xdiff = mouseDownPosition.x() - p.x();
		double ydiff = mouseDownPosition.y() - p.y();
		double dist = Math.sqrt(Math.pow(xdiff, 2) + Math.pow(ydiff, 2));
		return dist;
	}

	public void canConnect(RRWIcon outIcon, RRWIcon inIcon) {
		// TODO Auto-generated method stub
		if (outIcon.equals(inIcon)) return;
		Map<String, OutputSocket> outputs = outIcon.instance().outputs();
		Map<String, InputSocket> inputs = inIcon.instance().inputs();
		if (outputs.size() < 1 | inputs.size() < 1) return; // not possible if there are no connections.
		
		boolean canConnect = false;
		for (OutputSocket o : outputs.values()){
			if (canConnect) break;
			for (InputSocket i : inputs.values()){
				try {
					if (i.canConnect(o)) canConnect = true;
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} break;
			}
		}
		
		if (outIcon.equals(this)) shownRightEdge = canConnect ? imageRightEdgeG : imageRightEdgeR;
		else shownLeftEdge = canConnect ? imageLeftEdgeG : imageLeftEdgeR;
		
		
	}

	public void setAllLinesFinished(boolean b) {
		// TODO Auto-generated method stub
		
	}

	public QPointF getOldPos() {
		return oldPos;
	}

	public void setOldPos(QPointF oldPos) {
		System.out.println("Old position changing.");
		this.oldPos = oldPos;
	}

	public void resetLeftRightEdges() {
		// TODO Auto-generated method stub
		
	}

	public boolean nearPoint(QPointF point) {
		// TODO Auto-generated method stub
		QPointF pos = this.pos();
		if (
				(Math.abs(point.x() - (pos.x() + this.widgetSize.width() / 2)) < 50) 
				&
				(Math.abs(point.y() - (pos.y() + this.widgetSize.height() / 2)) < 50)
			) return true;
		else return false; 
	}
}
